from flask import request,jsonify,current_app,make_response,session

from . import passport_blue
# 导入自定义的状态码
from info.utils.response_code import RET

from info.utils.captcha.captcha import captcha

from info import redis_store,constants,db

import re,random

from info.models import User

from info.libs.yuntongxun.sms import CCP

from datetime import datetime


# 前端的index.html文件中的153行img标签的src属性，应当指向
# 当前的视图函数
@passport_blue.route('/image_code')
def generate_image_code():


    """
    生成图形验证码
    # var url='/image_code?image_code_id='+imageCodeId;
    1.获取uuid，img_code_id
    2.判断获取是否成功，如果没有uuid，直接终止程序运行
    3.调用captcha扩展包，生成图片验证码
    4.把图片验证码的内容，存入redis数据库，根据uuid作为后缀名
    5.把图片返回
    """
    image_code_id=request.args.get("image_code_id")

    if not image_code_id:

        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')

    name,text,image=captcha.generate_captcha()

    try:
        redis_store.setex('ImageCode_'+image_code_id,constants.IMAGE_CODE_REDIS_EXPIRES,text)
    except Exception as e:
        # 操作数据库，如果发生异常，需要记录项目日志
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='保存数据失败')
    response = make_response(image)
    return response

@passport_blue.route('/sms_code',methods=['POST'])
def send_sms_code():
    """
    发送短信
    获取参数------检查参数------业务处理------返回结果
    1.获取参数，前端Ajax发送过来的手机号，图片验证码，图片验证码的编号（uuid）
    2.检查参数的完整性，mobile,image_code,image_code_id
    3.检查手机号格式，正则
    4.尝试从redis中获取真实的图片验证码，根据uuid来从redis中拿出唯一的图片验证码
    5.判断是否成功
    6.如果获取成功，应该把redis中存储的图片验证码删了，因为图片验证码只能比较一次所以只能读取redis一次
    7.比较图片验证码是否正确
    8.生成6位数的随机数，作为短信验证码
    9.把短信验证码存入redis数据库中，便于后面用户注册时进行比较
    10.调用云通讯发送短信，保存发送结果
    11.判断是否成功
    12.返回结果
    :return:
    """
    # 获取参数
    mobile=request.json.get('mobile')
    image_code=request.json.get('image_code')
    image_code_id=request.json.get('image_code_id')
    # 检查参数完整性
    if not all([mobile,image_code,image_code_id]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数错误')
    # 用正则检测输入手机号的格式是否符合要求
    if not re.match(r'1[3456789]\d{9}$',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机号格式错误')
    # 从redis数据库中拿出图片验证码uuid与用户的图片验证码对比
    try:
        real_image_code=redis_store.get('ImageCode_'+image_code_id)
    except Exception as e:
        # 将错误记录在日志中
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='获取数据失败')
    # 检测图片验证码是否过期
    if not real_image_code:
        return jsonify(errno=RET.NODATA,errmsg='数据已过期')
    # 删除redis中的图片验证码,避免重复请求
    try:
        redis_store.delete('ImageCode_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
    # 如果验证码比对不成功返回错误信息， 加上lower让程序识别小写字母
    if real_image_code.lower()!=image_code.lower():
        return jsonify(errno=RET.DATAERR,errmsg='图片验证码错误')
    # 查询注册的手机号是否已经存在
    try:
        user=User.query.filter(User.mobile==mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        # 联网超时返回查询失败
        return jsonify(errno=RET.DATAEXIST,errmsg='查询数据失败')
    else:
        if user is not None:
            # 如果返回结果不是None返回该手机号已经注册过了
            return jsonify(erron=RET.DATAEXIST,errmsg='手机号已注册')
    # 设置短信验证码的长度为6位数
    sms_code='%06d'%random.randint(0,999999)
    print(sms_code)
    try:
        # 用redis实例调用setex方法   导入constants文件里的常量设置短信验证码在数据库里的有效期
        redis_store.setex('SMSCode_'+mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='保存短信验证码失败')
    try:
        ccp=CCP()
        # 调用第三方模块（云通讯）第一个参数是手机号，第二个是有效期设置为5分钟，第三个是1号测试模板
        result=ccp.send_template_sms(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60,1])
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.THIRDERR,errmsg='发送信息异常')
    if result==0:
        return jsonify(errno=RET.OK,errmsg='发送成功')
    else:
        return jsonify(errno=RET.THIRDERR,errmsg='发送失败')


@passport_blue.route('/register',methods=['POST'])
def register():
    # 获取参数
    mobile=request.json.get('mobile')
    sms_code=request.json.get('sms_code')
    password=request.json.get('password')
    # 检查参数完整性
    if not all([mobile,sms_code,passport_blue]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数错误')
    # 检查手机号格式
    if not re.match(r'1[3456789]\d{9}$',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机号格式错误')
    # 尝试从redis中获取短信验证码
    try:
        real_sms_code=redis_store.get('SMSCode_'+mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据失败')
    # 判断查询结果
    if not real_sms_code:
        return jsonify(errno=RET.NODATA,errmsg='数据过期')
    # 比较短信验证码是否正确
    if real_sms_code!=str(sms_code):
        return jsonify(errno=RET.DATAERR,errmsg='短信验证码错误')
    # 删除redis中的短信验证码
    try:
        redis_store.delete('SMSCode_'+mobile)
    except Exception as e:
        current_app.logger.error(e)

    # 查询用户是否注册过
    try:
        user=User.query.filter(User.mobile==mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询用户失败')
    else:
        if user is not None:
            return jsonify(errno=RET.DBERR,errmsg='手机号已注册')

    user=User()
    user.mobile=mobile
    user.nick_name=mobile
    user.password=password

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存数据失败')

    session['user_id']=user.id
    session['mobile']=mobile
    session['nick_name']=mobile
    return jsonify(errno=RET.OK,errmsg='注册成功')
@passport_blue.route('/login',methods=['POST'])
def login():
    mobile=request.json.get('mobile')
    password=request.json.get('password')

    if not all([mobile,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数错误')

    if not re.match(r'1[3456789]\d{9}$',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机号格式错误')

    try:
        user=User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据失败')
    if not user or not user.check_password(password):
        return jsonify(errno=RET.PWDERR,errmsg='用户名或密码错误')
    user.last_login=datetime.now()

    try:
        db.session.add(user)
        db.session.commit()

    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()

        return jsonify(errno=RET.DBERR,errmsg='保存数据失败')

    session['user_id']=user.id
    session['mobile']=mobile
    session['nike_name']=user.nick_name

    return jsonify(errno=RET.OK,errmsg='OK')

@passport_blue.route('/logout')
def logout():
    """
    是把服务器缓存的用户信息删除
    把redis中的缓存信息清除，不能使用flashdb
    :return:
    """
    session.pop('user_id',None)
    session.pop('mobile',None)
    session.pop('nick_name',None)

    return jsonify(errno=RET.OK,errmsg='退出成功')







    pass






